/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package assignment2;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;

/**
 * ProductViewer Class:
 * This class used to view all products that are currently available, along with all the products attributes
 * @author Vale
 *
 */
public class ProductViewer extends ProductList implements WindowListener, ActionListener {

    private JFrame viewProdFrame;
    private JScrollPane table;
    private JPanel headingPanel;
    private JPanel buttonPanel;
    private ProductList products;
    private InventoryList inventory;
    private JButton backButton;
    private JButton addProdButton;
    private JButton remProdButton;
    private JButton editProdButton;
    private JTable prodTable;
    private DefaultTableModel prodTableModel = new DefaultTableModel();
    private static final String HEADING_FONT = "Heading";
    private static final int HEADING_FONT_SIZE = 20;
    private static final String FRAME_HEADING = "Currently Available Products";
    private static final String GUI_TITLE = "Products Currently Available";
    private static final String BACK_BUTTON = "Back";
    private static final String ADDPROD_BUTTON = "Add New Product";
    private static final String REMPROD_BUTTON = "Remove Product";
    private static final String EDITPROD_BUTTON = "Edit Product";
    private static final int FRAME_WIDTH = 400;
    private static final int FRAME_HEIGHT = 500;
    private static final int BPANEL_ROWS = 2;
    private static final int BPANEL_COLS = 2;
    private static final int BUTTON_SPACING = 5;
    private static final int TABLE_COLS = 4;
    private static final String TABLE_HEAD_COL1 = "Product Name";
    private static final String TABLE_HEAD_COL2 = "Products Scheduled";
    private static final String TABLE_HEAD_COL3 = "Product Cost";
    private static final String TABLE_HEAD_COL4 = "Product Inventory";
    private static final String EMPTY_STRING = "";
    private static final String INV_SEPARATION = ", ";
    private static final int ZERO = 0;

    public ProductViewer(ProductList prodList, InventoryList invList) {
        //Create new Objects
        products = prodList;
        inventory = invList;
        viewProdFrame = new JFrame(FRAME_HEADING);
        headingPanel = new JPanel();
        buttonPanel = new JPanel();
        backButton = new JButton(BACK_BUTTON);
        addProdButton = new JButton(ADDPROD_BUTTON);
        remProdButton = new JButton(REMPROD_BUTTON);
        editProdButton = new JButton(EDITPROD_BUTTON);

        //Edit Frames properties
        viewProdFrame.addWindowListener(this);
        viewProdFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        viewProdFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        viewProdFrame.setLayout(new BorderLayout());

        //Format Heading
        JTextArea heading = new JTextArea(GUI_TITLE);
        Color bgColour = viewProdFrame.getBackground();
        heading.setBackground(bgColour);
        Font headerFont = new Font(HEADING_FONT, Font.BOLD, HEADING_FONT_SIZE);
        heading.setFont(headerFont);
        headingPanel.add(heading);

        //Add Buttons
        buttonPanel.setLayout(new GridLayout(BPANEL_ROWS, BPANEL_COLS, BUTTON_SPACING, BUTTON_SPACING));
        buttonPanel.add(addProdButton);
        addProdButton.addActionListener(new AddProduct());
        buttonPanel.add(remProdButton);
        remProdButton.addActionListener(new RemoveProduct());
        buttonPanel.add(editProdButton);
        editProdButton.addActionListener(new ProductEdit());
        buttonPanel.add(backButton);
        backButton.addActionListener(this);

        //Print main Product table
        printProductTable();

        //Add content to frame
        viewProdFrame.getContentPane().add(headingPanel, BorderLayout.NORTH);
        viewProdFrame.getContentPane().add(table, BorderLayout.CENTER);
        viewProdFrame.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
        viewProdFrame.setVisible(true);
    }

    /**
     * void actionPerformed(ActionEvent e) Method:
     * This is called when the "Back" button is pressed. It calls dispose(), which frees up all currently used resources by the current frame (viewProdFrame)
     * and consequently closes it.
     *
     */
    public void actionPerformed(ActionEvent e) {
        viewProdFrame.dispose();
    }

    /**
     * AddProduct Inner Class:
     * This inner class is used as a listener to the "Add Product" button. It instantiates a new instance of the ProductAdder class when the button is pressed, such
     * that a new Product can be added to the list.
     *
     */
    public class AddProduct implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            new ProductAdder(products, inventory, viewProdFrame);
        }
    }

    /**
     * RemoveProduct Inner Class:
     * This inner class is used as a listener to the "Remove Product" button. It removes the currently selected product from both the product list and GUI table display.
     *
     */
    public class RemoveProduct implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            int[] rowIndices = prodTable.getSelectedRows();
            for (int i = ZERO; i < rowIndices.length; i++) {
                products.remove(rowIndices[i]);
                prodTableModel.removeRow(rowIndices[i]);
            }
            prodTableModel.fireTableDataChanged();
        }
    }

    /**
     * ProductEdit Inner Class:
     * This inner class is used as a listener to the "Edit Product" button. It instantiates a new instance of the ProductEditor class when the button is pressed, such
     * that the currently selected product can be edited.
     *
     */
    public class ProductEdit implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            Product currProd = products.get(prodTable.getSelectedRow());
            new ProductEditor(currProd, products, inventory, viewProdFrame);
        }
    }

    /**
     * ProductViewer Constructor:
     * This is the constructor for the ProductViewer class. It takes both the current product list and inventory list as parameters, as it requires both to display the required
     * information about various products.
     *
     */
    
    /**
     * void windowOpened(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowOpened(WindowEvent e) {
    }

    /**
     * void windowClosing(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has been implemented such that if the frame is closed without using the specified "Back"
     * button, the resources used by the frame are released.
     *
     */
    public void windowClosing(WindowEvent e) {
        viewProdFrame.dispose();
    }

    /**
     * void windowClosed(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented, as its purpose has been covered by the 'windowClosing' event.
     *
     */
    public void windowClosed(WindowEvent e) {
    }

    /**
     * void windowIconified(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowIconified(WindowEvent e) {
    }

    /**
     * void windowDeiconified(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowDeiconified(WindowEvent e) {
    }

    /**
     * void windowActivated(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowActivated(WindowEvent e) {
    }

    /**
     * void windowDeactivated(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowDeactivated(WindowEvent e) {
    }

    /**
     * void printProductTable() Method:
     * This method is used to print the table of Products, and the data relavent to each. It also disables editing of cells.
     *
     */
    private void printProductTable() {
        int tableSize = products.getProdList().size();
        Object[][] rowData = new Object[tableSize][TABLE_COLS];
        Object[] columnNames = {TABLE_HEAD_COL1, TABLE_HEAD_COL2, TABLE_HEAD_COL3, TABLE_HEAD_COL4};
        for (int i = ZERO; i < tableSize; i++) {
            Object[] rowNum = {products.getProdList().get(i).getProdName(), products.getProdList().get(i).getProdSched(),products.getProdList().get(i).getProdCost() , getInventList(i)};
            rowData[i] = rowNum;
        }
        prodTable = new JTable(prodTableModel) {

            public boolean isCellEditable(int rowIndex, int colIndex) {
                return false;
            }
        };
        prodTableModel.setDataVector(rowData, columnNames);
        prodTable.setRowSelectionAllowed(true);
        table = new JScrollPane(prodTable);

    }

    /**
     * void getInventList(int i) Method:
     * This method is called by the printProductTable() method, and is used to create the string of inventory items for each respective product.
     *@return Returns a string of inventory items for the given product.
     */
    public String getInventList(int i) {
        InventoryList invList = products.getProdList().get(i).getInventList();
        String invString = EMPTY_STRING;
        for (int j = ZERO; j < invList.size(); j++) {
            String tempInv = invList.get(j).getInvName();
            if (j != ZERO && j != invList.size()) {
                invString = invString + INV_SEPARATION;
            }
            invString = invString + tempInv;
        }
        return invString;
    }
}
